package com.yhy.wxzn.wcs.device.plc.xj;

import HslCommunication.XJHelper;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.yhy.wxzn.common.utils.PlcGetByte;
import com.yhy.wxzn.common.utils.SpringUtil;
import com.yhy.wxzn.common.utils.WcsUtils;
import com.yhy.wxzn.wcs.device.netty.bean.ResultData;
import com.yhy.wxzn.wcs.device.plc.bean.*;
import com.yhy.wxzn.wcs.device.rgv.core.plc.ResultContainer;
import com.yhy.wxzn.wcs.device.rgv.bean.FourWayRgv;
import com.yhy.wxzn.wcs.service.IWcsDeviceInfoService;
import com.yhy.wxzn.wcs.service.IWcsDeviceLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.yhy.wxzn.wcs.SystemInit.fourWayRgvs;

/**
 * @Auther: 97354
 * @Date: 2023/11/6 16:08
 * @Description: 定时的读取点位数据并存储
 * @Version 1.0.0
 */

@Slf4j
public class XjPlcDriver extends Thread {

    public volatile XJHelper xjHelper;
    private volatile String plcIp;
    private volatile int port;
    private volatile String plcName;
    private final byte station = 1;
    private volatile int deviceConnected = 0;

    //点位信息
    private volatile PlcDriverData driverData = new PlcDriverData();
    private IWcsDeviceLogService deviceLogService;
    private IWcsDeviceInfoService deviceInfoService;

    public XjPlcDriver(String plcIp, int port, String plcName) {
        this.plcIp = plcIp;
        this.port = port;
        this.plcName = plcName;
        xjHelper = new XJHelper(this.plcIp, this.port, station);
    }

    private void init() {
        deviceLogService = SpringUtil.getBean(IWcsDeviceLogService.class);
        deviceInfoService = SpringUtil.getBean(IWcsDeviceInfoService.class);
    }

    @Override
    public void run() {
        while (true) {
            try {
                if (SpringUtil.getApplicationContext() != null) {
                    init();
                    break;
                }
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        xjHelper.connect(plcIp);
        connectStatus();
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        if (!CollectionUtils.isEmpty(driverData.getXJPtransLinePlcMap())) {
            executorService.execute(() -> {
                while (true) {
                    try {
                        if (!xjHelper.isConnectd()) {
                            xjHelper.connect(plcIp);
                            log.error("plc名：{},ip:{},port:{},连接PLC失败,正在重新连接中...",plcName,plcIp,port);
                            sleep(30000);
                            continue;
                        }
                        //同步输送线
                        synXJPTransmission();
                    } catch (Exception ex) {
                        log.error("同步输送线处理异常", ex);
                    }
                    WcsUtils.sleep(100);
                }
            });
        }

        if (!CollectionUtils.isEmpty(driverData.getXJPhoistPlcMap())) {
            executorService.execute(() -> {
                while (true) {
                    try {
                        if (!xjHelper.isConnectd()) {
                            xjHelper.connect(plcIp);
                            log.error("plc名：{},ip:{},port:{},连接PLC失败,正在重新连接中...",plcName,plcIp,port);
                            sleep(30000);
                            continue;
                        }
                        //同步提升机
                        synXJPHoist();
                    } catch (Exception ex) {
                        log.error("同步提升机处理异常", ex);
                    }
                    WcsUtils.sleep(100);
                }
            });
        }

        if (!CollectionUtils.isEmpty(driverData.getFourCarPlcMap())) {
            executorService.execute(() -> {
                while (true) {
                    try {
                        if (!xjHelper.isConnectd()) {
                            xjHelper.connect(plcIp);
                            log.error("plc名：{},ip:{},port:{},连接PLC失败,正在重新连接中...",plcName,plcIp,port);
                            sleep(30000);
                            continue;
                        }
                        //同步四向车状态
                            syncSxCar();
                    } catch (Exception ex) {
                        log.error("同步四向车处理异常", ex);
                    }
                    WcsUtils.sleep(100);
                }
            });
        }

    }

    private void synXJPHoist() {
        driverData.getXJPhoistPlcMap().entrySet().parallelStream().forEach(hoistPlcEntry -> {
            String coord = hoistPlcEntry.getKey();
             XJPHoistPlc hoistPlc = hoistPlcEntry.getValue();
            if (null == hoistPlc) {
                return;
            }
            ResultData resultData = read(hoistPlc.getReadAddress(), 14, hoistPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                hoistPlc.setTaskNoR(PlcGetByte.bytesToInt16Hight2(bytes, 0));
                hoistPlc.setLayer(PlcGetByte.bytesToInt16Hight2(bytes, 2));
                hoistPlc.setStatus(PlcGetByte.bytesToInt16Hight2(bytes, 4));
                hoistPlc.setWorkStatus(PlcGetByte.bytesToInt16Hight2(bytes, 6));
                hoistPlc.setIsHaveCargo(PlcGetByte.bytesToInt16Hight2(bytes, 8));
                hoistPlc.setIsHaveCar(PlcGetByte.bytesToInt16Hight2(bytes, 10));
                hoistPlc.setTaskStatus(PlcGetByte.bytesToInt16Hight2(bytes, 12));
            } else {
                String msg = String.format("读取提升机点位--%s--地址--%s--数据失败,失败原因为--%s", coord, hoistPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(coord, msg);
            }
            ResultData writeData = read(hoistPlc.getWriteAddress(), 16, hoistPlc.getRefreshTime());
            if (writeData.isSuccess()) {
                byte[] dataValue = (byte[]) writeData.getValue();
                hoistPlc.setTaskNoW(PlcGetByte.bytesToInt16Hight2(dataValue, 0));
                hoistPlc.setTaskType(PlcGetByte.bytesToInt16Hight2(dataValue, 2));

                hoistPlc.setSourceFloor(PlcGetByte.bytesToInt16Hight2(dataValue, 4));
                hoistPlc.setTargetFloor(PlcGetByte.bytesToInt16Hight2(dataValue, 6));
                hoistPlc.setCarIntoOrLeaveLifterFinished(PlcGetByte.bytesToInt16Hight2(dataValue, 10));
                hoistPlc.setTaskStatus(PlcGetByte.bytesToInt16Hight2(dataValue, 12));
                hoistPlc.setTaskEnd(PlcGetByte.bytesToInt16Hight2(dataValue, 14));
            }
        });
    }

    private void synXJPTransmission() {
        driverData.getXJPtransLinePlcMap().entrySet().parallelStream().forEach(transmissionPlcEntry -> {
            String coord = transmissionPlcEntry.getKey();
            XJPTransmissionPlc transmissionPlc = transmissionPlcEntry.getValue();
            if (null == transmissionPlc) {
                return;
            }
            ResultData resultData = read(transmissionPlc.getReadAddress(), 8, transmissionPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                int taskNoR = PlcGetByte.bytesToInt16Hight2(bytes, 0);
                int lifterPermitTransInPort = PlcGetByte.bytesToInt16Hight2(bytes, 2);
                int literQuestOutPort = PlcGetByte.bytesToInt16Hight2(bytes, 4);
                int startScan = PlcGetByte.bytesToInt16Hight2(bytes, 6);


                transmissionPlc.setTaskNoR(taskNoR);
                transmissionPlc.setLifterPermitTransInPort(lifterPermitTransInPort);
                transmissionPlc.setLiterQuestOutPort(literQuestOutPort);
                transmissionPlc.setStartScan(startScan);
            } else {
                String msg = String.format("读取输送线点位--%s--地址--%s--数据失败,失败原因为--%s", coord, transmissionPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(coord, msg);
            }
            ResultData writeData = read(transmissionPlc.getWriteAddress(), 12, transmissionPlc.getRefreshTime());
            if (writeData.isSuccess()) {
                byte[] dataValue = (byte[]) writeData.getValue();
                transmissionPlc.setIsScanBarcode(PlcGetByte.bytesToInt16Hight2(dataValue, 0));
                transmissionPlc.setGetCargoFinished(PlcGetByte.bytesToInt16Hight2(dataValue, 2));
                transmissionPlc.setTaskNoW(PlcGetByte.bytesToInt16Hight2(dataValue, 4));
                transmissionPlc.setTaskType(PlcGetByte.bytesToInt16Hight2(dataValue, 6));
                transmissionPlc.setTargetStation(PlcGetByte.bytesToInt16Hight2(dataValue, 8));
                transmissionPlc.setPutCargoFinished(PlcGetByte.bytesToInt16Hight2(dataValue, 10));

            }
        });
    }

    private void syncSxCar() {
        driverData.getFourCarPlcMap().entrySet().parallelStream().forEach(fourCarPlcEntry -> {
            String carNo = fourCarPlcEntry.getKey();
            FourCarPlc fourCarPlc = fourCarPlcEntry.getValue();
            if (null == fourCarPlc) {
                return;
            }


            writeRgvHeardBeat();

            ResultData resultData = read(fourCarPlc.getReadAddress(), 34, fourCarPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                int carStatus = PlcGetByte.bytesToInt16Hight2(bytes, 0);
                int dcdl = PlcGetByte.bytesToInt16Hight2(bytes, 2);
                int errorType = PlcGetByte.bytesToInt16Hight2(bytes, 4);
                int twoCode = PlcGetByte.bytesToInt16Hight2(bytes, 6);
                int xvar = PlcGetByte.bytesToInt16Hight2(bytes, 8);
                int yvar = PlcGetByte.bytesToInt16Hight2(bytes, 10);
                int dcdy = PlcGetByte.bytesToInt16Hight2(bytes, 12);
                int dcwd = PlcGetByte.bytesToInt16Hight2(bytes, 14);
                int jgcjcgq = PlcGetByte.bytesToInt16Hight2(bytes, 16);
                int heartBeat = PlcGetByte.bytesToInt16Hight2(bytes, 18);
                int position = PlcGetByte.bytesToInt16Hight2(bytes, 20);
                int sjzt = PlcGetByte.bytesToInt16Hight2(bytes, 22);
                int beFinish = PlcGetByte.bytesToInt16Hight2(bytes, 24);
                int speed = PlcGetByte.bytesToInt16Hight2(bytes, 26);
                int cdzt = PlcGetByte.bytesToInt16Hight2(bytes, 28);
                int direction = PlcGetByte.bytesToInt16Hight2(bytes, 30);
                int taskNo = PlcGetByte.bytesToInt16Hight2(bytes, 32);


                String msg = fourCarChange(fourCarPlc, carStatus, xvar, yvar, heartBeat, beFinish);

                fourCarPlc.setReceiveTime(System.currentTimeMillis());
                fourCarPlc.setCarStatus(carStatus);
                fourCarPlc.setDcdl(dcdl);
                fourCarPlc.setErrorType(errorType);
                fourCarPlc.setTwoCode(String.valueOf(twoCode));
                fourCarPlc.setXvar(xvar);
                fourCarPlc.setYvar(yvar);
                fourCarPlc.setDcdy(dcdy);
                fourCarPlc.setDcwd(dcwd);
                fourCarPlc.setJgcjcgq(jgcjcgq);
                fourCarPlc.setHeartBeat(heartBeat);
                fourCarPlc.setPosition(position);
                fourCarPlc.setSjzt(sjzt);
                fourCarPlc.setBeFinish(beFinish);
                fourCarPlc.setSpeed(speed);
                fourCarPlc.setCdzt(cdzt);
                fourCarPlc.setDirection(direction);
                fourCarPlc.setTaskNo(taskNo);


                //把带任务号的数据存入ResultContainer
                if (fourCarPlc.getTaskNo() != 0 && CollUtil.isNotEmpty(fourWayRgvs)) {
                    for (FourWayRgv fourWayRgv : fourWayRgvs) {
                        if (fourWayRgv.getFourCarPlc().getCarNo().equals(carNo)) {
                            FourCarPlc target = new FourCarPlc();
                            BeanUtils.copyProperties(fourCarPlc, target);
                            ResultContainer.getResultContainer(fourWayRgv).putTaskResult(fourCarPlc.getTaskNo(), target);
                            break;
                        }
                    }
                }


                if (StringUtils.isNotEmpty(msg)) {
                    log.info("同步四向车{}数据结束，fourCarPlc：{}，变化值：{}", carNo, JSON.toJSONString(fourCarPlc), msg);
                }
            } else {
                String msg = String.format("读取四向车地址--%s--数据失败,失败原因为--%s", fourCarPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(carNo, msg);
            }
            //同步写入信息
            ResultData writeData = read(fourCarPlc.getWriteAddress(), 16, fourCarPlc.getRefreshTime());
            ResultData w1 = read("HD4000", 2, fourCarPlc.getRefreshTime());
            ResultData w2 = read("HD2000", 4, fourCarPlc.getRefreshTime());
            ResultData w3 = read("HD3000", 4, fourCarPlc.getRefreshTime());
            if (writeData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                int xslc = PlcGetByte.bytesToInt32Hight(bytes, 0);
                int wspeed = PlcGetByte.bytesToInt16Hight2(bytes, 4);
                int runAway = PlcGetByte.bytesToInt16Hight2(bytes, 6);
                int start = PlcGetByte.bytesToInt16Hight2(bytes, 8);
                int updown = PlcGetByte.bytesToInt16Hight2(bytes, 10);
                int wheart = PlcGetByte.bytesToInt16Hight2(bytes, 12);
                int chargOrder = PlcGetByte.bytesToInt16Hight2(bytes, 14);
                if (w1.isSuccess()) {
                    byte[] temp = (byte[]) w1.getValue();
                    int qrCode = PlcGetByte.bytesToInt16Hight2(temp, 0);
//                    fourCarPlc.setQrCode(qrCode);
                }
                if (w2.isSuccess()) {
                    byte[] temp = (byte[]) w2.getValue();
                    int xValue = PlcGetByte.bytesToInt32Hight(temp, 0);
//                    fourCarPlc.setXValue(xValue);
                }
                if (w3.isSuccess()) {
                    byte[] temp = (byte[]) w3.getValue();
                    int yValue = PlcGetByte.bytesToInt32Hight(temp, 0);
//                    fourCarPlc.setYValue(yValue);
                }
                fourCarPlc.setWXslc(xslc);
                fourCarPlc.setWSpeed(wspeed);
                fourCarPlc.setWRunAway(runAway);
                fourCarPlc.setWStart(start);
                fourCarPlc.setWUpdown(updown);
                fourCarPlc.setWHeart(wheart);
                fourCarPlc.setWChargeOrder(chargOrder);
            }
        });
    }

    private void writeRgvHeardBeat() {
        write("HD5", 1);
    }

    private String fourCarChange(FourCarPlc fourCarPlc, int carStatus, int xvar, int yvar, int heartBeat, int beFinish) {
        StringBuilder msg = new StringBuilder();
        if (fourCarPlc.getCarStatus() != carStatus) {
            msg.append("[carStatus：").append(fourCarPlc.getCarStatus()).append("!=").append(carStatus).append("]，");
        }
//        if (fourCarPlc.getXvar() != xvar) {
//            msg.append("[xvar：").append(fourCarPlc.getXvar()).append("!=").append(xvar).append("]，");
//        }
//        if (fourCarPlc.getYvar() != yvar) {
//            msg.append("[yvar：").append(fourCarPlc.getYvar()).append("!=").append(yvar).append("]，");
//        }
        if (fourCarPlc.getHeartBeat() != heartBeat) {
            msg.append("[heartBeat：").append(fourCarPlc.getHeartBeat()).append("!=").append(heartBeat).append("]，");
        }
        if (fourCarPlc.getBeFinish() != beFinish) {
            msg.append("[beFinish：").append(fourCarPlc.getBeFinish()).append("!=").append(beFinish).append("]，");
        }
        return msg.toString();
    }

    public synchronized ResultData write(String address, Object value) {
        ResultData resultData = notConnect();
        if (resultData != null) {
            return resultData;
        }
        if (value instanceof byte[]) {
            resultData = xjHelper.write(address, (byte[]) value);
        } else if (value instanceof Integer) {
            resultData = xjHelper.write(address, (int) value);
        } else if (value instanceof Short) {
            resultData = xjHelper.write(address, (short) value);
        } else if (value instanceof Boolean) {
            resultData = xjHelper.write(address, (boolean) value);
        } else {
            resultData = new ResultData();
            resultData.setConnecd(false);
            resultData.setSuccess(false);
            resultData.setMessage("地址类型有误！");
        }
        return resultData;
    }

    private String pileupChange(StackerPlc pileupPlc, int callOutBound, int qty, int status, int backup) {
        StringBuilder msg = new StringBuilder();
        if (pileupPlc.getCallOutBound() != callOutBound) {
            msg.append("[CallOutBound：").append(pileupPlc.getCallOutBound()).append("!=").append(callOutBound).append("]，");
        }
        if (pileupPlc.getQty() != qty) {
            msg.append("[Qty：").append(pileupPlc.getQty()).append("!=").append(qty).append("]，");
        }
        if (pileupPlc.getStatus() != status) {
            msg.append("[Status：").append(pileupPlc.getStatus()).append("!=").append(status).append("]，");
        }
        if (pileupPlc.getBackup() != backup) {
            msg.append("[Backup：").append(pileupPlc.getBackup()).append("!=").append(backup).append("]，");
        }
        return msg.toString();
    }

    private String demolishChange(StackerPlc demolishPlc, int callInBound, int qty, int status, int backup) {
        StringBuilder msg = new StringBuilder();
        if (demolishPlc.getCallInBound() != callInBound) {
            msg.append("[CallInBound：").append(demolishPlc.getCallInBound()).append("!=").append(callInBound).append("]，");
        }
        if (demolishPlc.getQty() != qty) {
            msg.append("[Qty：").append(demolishPlc.getQty()).append("!=").append(qty).append("]，");
        }
        if (demolishPlc.getStatus() != status) {
            msg.append("[Status：").append(demolishPlc.getStatus()).append("!=").append(status).append("]，");
        }
        if (demolishPlc.getBackup() != backup) {
            msg.append("[Backup：").append(demolishPlc.getBackup()).append("!=").append(backup).append("]，");
        }
        return msg.toString();
    }


    private void synHoist() {
        if (CollectionUtils.isEmpty(driverData.getHoistPlcMap())) {
            return;
        }
        driverData.getHoistPlcMap().entrySet().parallelStream().forEach(hoistPlcEntry -> {
            hoistReadSync(hoistPlcEntry);
            hoistAdditionalDataSync(hoistPlcEntry);
            hoistWriteSync(hoistPlcEntry);
        });
    }

    private void hoistWriteSync(Map.Entry<String, HoistPlc> hoistPlcEntry) {
        String hostId = hoistPlcEntry.getKey();
        HoistPlc hoistPlc = hoistPlcEntry.getValue();
        //读取写入信息
        ResultData writeData = read(hoistPlc.getWriteAddress(), 7, hoistPlc.getRefreshTime());

        if (!writeData.isSuccess()) {
            log.error("读取提升机写信息失败:{}",writeData.getMessage());
            return;
        }

        byte[] bytes = (byte[]) writeData.getValue();
        int sourceFloor = PlcGetByte.bytesToInt16Hight2(bytes, 0);
        int sourceDevice = PlcGetByte.bytesToInt16Hight2(bytes, 2);
        int targetFloor = PlcGetByte.bytesToInt16Hight2(bytes, 4);
        int targetDevice = PlcGetByte.bytesToInt16Hight2(bytes, 6);
        int taskType = PlcGetByte.bytesToInt16Hight2(bytes, 8);
        int taskNo = PlcGetByte.bytesToInt32Hight(bytes, 10);

        hoistPlc.setSourceFloor(sourceFloor);
        hoistPlc.setSourceDevice(sourceDevice);
        hoistPlc.setTargetFloor(targetFloor);
        hoistPlc.setTargetDevice(targetDevice);
        hoistPlc.setTaskType(taskType);
        hoistPlc.setTaskNo(taskNo);
    }


    private void hoistAdditionalDataSync(Map.Entry<String, HoistPlc> hoistPlcEntry) {
        HoistPlc hoistPlc = hoistPlcEntry.getValue();
        ResultData resultData = read("D10", 1, hoistPlc.getRefreshTime());
        if (!resultData.isSuccess()) {
          log.error("读取提升机额外信息失败:{}",resultData.getMessage());
          return;
        }

        byte[] bytes = (byte[]) resultData.getValue();

        boolean haveStock = PlcGetByte.getBitValue(bytes[0], 2);
        boolean haveCar = PlcGetByte.getBitValue(bytes[0], 3);
        boolean accessCar = PlcGetByte.getBitValue(bytes[0], 4);

        hoistPlc.setHaveStock(haveStock);
        hoistPlc.setHaveCar(haveCar);
        hoistPlc.setAccessCar(accessCar);


        log.info("haveStock:{},haveCar:{},accessCar:{}"
                ,haveStock,haveCar,accessCar);
    }

    private void hoistReadSync(Map.Entry<String, HoistPlc> hoistPlcEntry) {
        String hostId = hoistPlcEntry.getKey();
        HoistPlc hoistPlc = hoistPlcEntry.getValue();
        ResultData resultData = read(hoistPlc.getReadAddress(), 6, hoistPlc.getRefreshTime());
        if (resultData.isSuccess()) {
            byte[] bytes = (byte[]) resultData.getValue();
            int taskId = PlcGetByte.bytesToInt32Hight(bytes, 0);
            int floor = PlcGetByte.bytesToInt16Hight2(bytes, 4);
            int autoStatus = PlcGetByte.bytesToInt16Hight2(bytes, 6);
            int workStatus = PlcGetByte.bytesToInt16Hight2(bytes, 8);
            int faultCode = PlcGetByte.bytesToInt16Hight2(bytes, 10);

            String msg = hoistChange(hoistPlc, taskId, floor, autoStatus, workStatus, faultCode);

            hoistPlc.setTaskId(taskId);
            hoistPlc.setFloor(floor);
            hoistPlc.setAutoStatus(autoStatus);
            hoistPlc.setWorkStatus(workStatus);
            hoistPlc.setFaultCode(faultCode);

            if (StringUtils.isNotEmpty(msg)) {
                log.info("同步提升机{}数据结束，hoistPlc：{}，变化值：{}", hostId, JSON.toJSONString(hoistPlc), msg);
            }
        } else {
            String msg = String.format("读取提升机地址--%s--数据失败,失败原因为--%s", hoistPlc.getReadAddress(), resultData.getMessage());
            deviceLogService.genCoordLog(hostId, msg);
        }


    }

    private String hoistChange(HoistPlc hoistPlc, int taskId, int floor, int autoStatus, int workStatus, int faultCode) {
        StringBuilder msg = new StringBuilder();
        if (hoistPlc.getTaskId() != taskId) {
            msg.append("[DeviceNum：").append(hoistPlc.getTaskId()).append("!=").append(taskId).append("]，");
        }
        if (hoistPlc.getFloor() != floor) {
            msg.append("[Floor：").append(hoistPlc.getFloor()).append("!=").append(floor).append("]，");
        }
        if (hoistPlc.getAutoStatus() != autoStatus) {
            msg.append("[AutoStatus：").append(hoistPlc.getAutoStatus()).append("!=").append(autoStatus).append("]，");

        }
        if (hoistPlc.getWorkStatus() != workStatus) {
            msg.append("[WorkStatus：").append(hoistPlc.getWorkStatus()).append("!=").append(workStatus).append("]，");
        }

        if (hoistPlc.getFaultCode() != faultCode) {
            msg.append("[FaultCode：").append(hoistPlc.getFaultCode()).append("!=").append(faultCode).append("]，");
        }

        return msg.toString();
    }


    private void synTransmission() {
        if (CollectionUtils.isEmpty(driverData.getTransLinePlcMap())) {
            return;
        }
        driverData.getTransLinePlcMap().entrySet().parallelStream().forEach(transmissionPlcEntry -> {
            String coord = transmissionPlcEntry.getKey();
            TransmissionPlc transmissionPlc = transmissionPlcEntry.getValue();
            if (null == transmissionPlc) {
                return;
            }
            ResultData resultData = read(transmissionPlc.getReadAddress(), 16, transmissionPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                int deviceNum = PlcGetByte.bytesToInt32Hight(bytes, 0);
                int inPlaceNum = PlcGetByte.bytesToInt16Hight2(bytes, 4);
                int haveStock = PlcGetByte.bytesToInt16Hight2(bytes, 6);
                int status = PlcGetByte.bytesToInt16Hight2(bytes, 8);
                int faultCode = PlcGetByte.bytesToInt16Hight2(bytes, 10);
                int workStatus = PlcGetByte.bytesToInt16Hight2(bytes, 12);
                int backup = PlcGetByte.bytesToInt16Hight2(bytes, 14);

                String msg = transmissionChange(transmissionPlc, deviceNum, inPlaceNum, haveStock, status, faultCode, workStatus, backup);

                transmissionPlc.setDeviceNum(deviceNum);
                transmissionPlc.setInPlaceNum(inPlaceNum);
                transmissionPlc.setHaveStock(haveStock);
                transmissionPlc.setStatus(status);
                transmissionPlc.setFaultCode(faultCode);
                transmissionPlc.setWorkStatus(workStatus);
                transmissionPlc.setBackup(backup);

                if (StringUtils.isNotEmpty(msg)) {
                    log.info("同步输送线点位{}数据结束，transmissionPlc：{}，变化值：{}", coord, JSON.toJSONString(transmissionPlc), msg);
                }
            } else {
                String msg = String.format("读取输送线点位--%s--地址--%s--数据失败,失败原因为--%s", coord, transmissionPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(coord, msg);
            }
            ResultData writeData = read(transmissionPlc.getWriteAddress(), 12, transmissionPlc.getRefreshTime());
            if (writeData.isSuccess()) {
                byte[] dataValue = (byte[]) writeData.getValue();
                int target = PlcGetByte.bytesToInt16Hight2(dataValue, 0);
                int taskType = PlcGetByte.bytesToInt16Hight2(dataValue, 2);
                int taskNo = PlcGetByte.bytesToInt32Hight(dataValue, 4);
                int getFinish = PlcGetByte.bytesToInt16Hight2(dataValue, 8);
                int putFinish = PlcGetByte.bytesToInt16Hight2(dataValue, 10);
                transmissionPlc.setTarget(target);
                transmissionPlc.setTaskType(taskType);
                transmissionPlc.setTaskNo(taskNo);
                transmissionPlc.setGetFinish(getFinish);
                transmissionPlc.setPutFinish(putFinish);
            }
        });
    }

    private String transmissionChange(TransmissionPlc transmissionPlc, int deviceNum, int inPlaceNum, int haveStock,
                                      int status, int faultCode, int workStatus, int backup) {
        StringBuilder msg = new StringBuilder();
        if (transmissionPlc.getDeviceNum() != deviceNum) {
            msg.append("[DeviceNum：").append(transmissionPlc.getDeviceNum()).append("!=").append(deviceNum).append("]，");
        }
        if (transmissionPlc.getInPlaceNum() != inPlaceNum) {
            msg.append("[InPlaceNum：").append(transmissionPlc.getInPlaceNum()).append("!=").append(inPlaceNum).append("]，");
        }
        if (transmissionPlc.getHaveStock() != haveStock) {
            msg.append("[HaveStock：").append(transmissionPlc.getHaveStock()).append("!=").append(haveStock).append("]，");
        }
        if (transmissionPlc.getStatus() != status) {
            msg.append("[Status：").append(transmissionPlc.getStatus()).append("!=").append(status).append("]，");
            //故障上报
//            if (status == 5) {
//                String codeStr = transmissionPlc.getDevice() + " 输送线故障，故障代码：" + faultCode + "，故障描述：" + InitDataListener.faultMap.get(faultCode);
//                mcsAlarmLogService.insertMcsAlarmLog(String.valueOf(transmissionPlc.getDevice()), 6, "1", codeStr);
//            }
//            if (transmissionPlc.getStatus() == 5) {
//                mcsAlarmLogService.insertMcsAlarmLog(String.valueOf(transmissionPlc.getDevice()), 6, "2", transmissionPlc.getDevice() + " 输送线故障恢复");
//            }
        }
        if (transmissionPlc.getFaultCode() != faultCode) {
            msg.append("[FaultCode：").append(transmissionPlc.getFaultCode()).append("!=").append(faultCode).append("]，");
        }
        if (transmissionPlc.getWorkStatus() != workStatus) {
            msg.append("[WorkStatus：").append(transmissionPlc.getWorkStatus()).append("!=").append(workStatus).append("]，");
        }
        if (transmissionPlc.getBackup() != backup) {
            msg.append("[Backup：").append(transmissionPlc.getBackup()).append("!=").append(backup).append("]，");
        }
        return msg.toString();
    }

    private void synPort() {
        if (CollectionUtils.isEmpty(driverData.getPortPlcMap())) {
            return;
        }
        driverData.getPortPlcMap().entrySet().parallelStream().forEach(portPlcEntry -> {
            String deviceId = portPlcEntry.getKey();
            PortPlc portPlc = portPlcEntry.getValue();
            if (null == portPlc) {
                return;
            }
            ResultData resultData = read(portPlc.getReadAddress(), 36, portPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                byte[] bytes = (byte[]) resultData.getValue();
                String barCode = PlcGetByte.byteToString(bytes, 0, 16).replace('?', ' ').trim();
                String weight = PlcGetByte.byteToString(bytes, 32, 16).replace('?', ' ').trim();
                int detection = PlcGetByte.bytesToInt16Hight2(bytes, 64);
                int plcNum = PlcGetByte.bytesToInt16Hight2(bytes, 68);

                String msg = portChange(portPlc, barCode, weight, detection, plcNum);

                if (plcNum > 0 && plcNum != portPlc.getPlcNum()) {
                    portPlc.setChange(true);
                }
                portPlc.setBcrCode(barCode);
                portPlc.setWeight(weight);
                portPlc.setDetection(detection);
                portPlc.setPlcNum(plcNum);

                if (StringUtils.isNotEmpty(msg)) {
                    log.info("同步出入库口设备ID{}数据结束，portPlc：{}，变化值：{}", deviceId, JSON.toJSONString(portPlc), msg);
                }
            } else {
                String msg = String.format("读取出入库口设备ID--%s--地址--%s--数据失败,失败原因为--%s", deviceId, portPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(deviceId, msg);
            }
        });
    }

    private String portChange(PortPlc portPlc, String barCode, String weight, int detection, int plcNum) {
        StringBuilder msg = new StringBuilder();
        if (!barCode.equals(portPlc.getBcrCode())) {
            msg.append("[BcrCode：").append(portPlc.getBcrCode()).append("!=").append(barCode).append("]，");
        }
        if (!weight.equals(portPlc.getWeight())) {
            msg.append("[Weight：").append(portPlc.getWeight()).append("!=").append(weight).append("]，");
        }
        if (portPlc.getDetection() != detection) {
            msg.append("[Detection：").append(portPlc.getDetection()).append("!=").append(detection).append("]，");
        }
        if (portPlc.getPlcNum() != plcNum) {
            msg.append("[PlcNum：").append(portPlc.getPlcNum()).append("!=").append(plcNum).append("]，");
        }
        return msg.toString();
    }

    private void synHeartbeat() {
        if (CollectionUtils.isEmpty(driverData.getHeartBeatPlcMap())) {
            return;
        }
        driverData.getHeartBeatPlcMap().entrySet().parallelStream().forEach(heartBeatPlcEntry -> {
            HeartBeatPlc heartBeatPlc = heartBeatPlcEntry.getValue();
            ResultData resultData = read(heartBeatPlc.getReadAddress(), 1, heartBeatPlc.getRefreshTime());
            if (resultData.isSuccess()) {
                short heartbeat = (short) resultData.getValue();
                if (heartBeatPlc.getHeartbeat() != heartbeat) {
                    heartBeatPlc.setChange(true);
                }
                heartBeatPlc.setHeartbeat(heartbeat);
            } else {
                String msg = String.format("读取心跳点位--%s--设备ID--%s--数据失败,失败原因为--%s", heartBeatPlcEntry.getKey(), heartBeatPlc.getReadAddress(), resultData.getMessage());
                deviceLogService.genCoordLog(heartBeatPlcEntry.getKey(), msg);
            }
        });
    }

    public ResultData read(String address, int length, Integer refreshTime) {
        ResultData resultData = notConnect();
        if (resultData != null) {
            return resultData;
        }
        try {
            sleep(refreshTime == null ? 50 : refreshTime);
            return xjHelper.readBytes(address, length);
        } catch (InterruptedException ex) {
            log.error("读取PLC地址{}异常", address, ex);
            return null;
        }
    }

    private ResultData notConnect() {
        if (xjHelper.isConnectd()) {
            return null;
        }
        ResultData rd = new ResultData();
        rd.setConnecd(false);
        rd.setSuccess(false);
        rd.setMessage("当前与PLC通信断开！");
        return rd;
    }

    private boolean isSuccess() {
        boolean status = xjHelper.isConnectd();
        if (!status) {
            xjHelper.close();
            String content = plcName + "：【" + plcIp + " 】重新连接";
            deviceLogService.genCoordLog(plcName, content);
            setAutoByOffline();
            xjHelper.connect(plcIp);
            connectStatus();
        }
        return status;
    }

    private void setAutoByOffline() {
        driverData.getHoistPlcMap().forEach((k, v) -> v.setAuto(false));
        driverData.getPortPlcMap().forEach((k, v) -> v.setAuto(false));
        driverData.getTransLinePlcMap().forEach((k, v) -> v.setAuto(false));
        driverData.getFourCarPlcMap().forEach((k, v) -> v.setAuto(false));
    }

    private void connectStatus() {
        StringBuffer msg = new StringBuffer();
        if (!xjHelper.isConnectd() && deviceConnected == 0) {
            deviceConnected = 1;
            msg.append("PLC分组号：【" + plcName + "】IP地址:【" + plcIp + "】 已断开");
        } else if (xjHelper.isConnectd() && deviceConnected == 0) {
            msg.append("PLC分组号：【" + plcName + "】IP地址:【" + plcIp + "】 已连接");
            deviceConnected = 2;
        } else if (xjHelper.isConnectd() && deviceConnected == 1) {
            deviceConnected = 2;
            msg.append("PLC分组号：【" + plcName + "】IP地址:【" + plcIp + "】 已连接");
        } else if (!xjHelper.isConnectd() && deviceConnected == 2) {
            msg.append("PLC分组号：【" + plcName + "】IP地址:【" + plcIp + "】 已断开");
            deviceConnected = 1;
        }
        if (msg.length() > 0) {
            deviceLogService.genCoordLog(plcName, msg.toString());
        }
    }

    public synchronized boolean savePlcLog(String address, Object value, Map map) {
        ResultData resultData = write(address, value);
        log.info("{}地址:{}写值结果：{}", plcName, address, JSON.toJSONString(resultData));
        StringBuilder msg = new StringBuilder(String.format("%s号PLC，地址--%s", plcName, address));
        if (resultData.isSuccess()) {
            msg.append(String.format("--写值成功,写值信息为--%s", map.toString()));
            deviceLogService.genCoordLog(address, msg.toString());
        } else {
            msg.append(String.format("--写值失败,失败原因为--%s", resultData.getMessage()));
            deviceLogService.genCoordLog(address, msg.toString());
        }
        return resultData.isSuccess();
    }

    public void reconnect() {
        xjHelper.close();
        String msg = plcName + "：【" + plcIp + "】重新连接";
        deviceLogService.genCoordLog(plcName, msg);
        xjHelper.connect(plcIp);
        connectStatus();
    }


    public PlcDriverData getDriverData() {
        return driverData;
    }

}
